package com.caunock.sqlbuilder.adapter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.caunock.sqlbuilder.meta.Column;
import com.caunock.sqlbuilder.meta.Index;
import com.caunock.sqlbuilder.meta.Table;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 抽象适配器
 * @author 秦先生
 */
public abstract class AbstractDDLAdapter implements DDLAdapter {

    /**
     * 标识符
     */
    protected static final String DELIMITER = ".";
    protected static final String COMMA = ",";
    protected static final String NAME_QUOTE = "'";

    @Override
    public StringBuilder buildCreate(StringBuilder builder, Table meta) {
        String name = meta.getName();
        if (StrUtil.isBlank(name)) {
            meta.setName("Untitled");
        }
        builder.append("CREATE TABLE ");
        tableName(builder, meta);
        body(builder, meta);
        comment(builder, meta);
        builder.append(";");
        // 构建完毕之后，构建特殊属性  主键,索引,字段描述,表描述
        tableCommentOn(builder, meta);
        columnCommentOn(builder, meta);
        indexes(builder, meta);
        return builder;
    }

    /**
     * table[命令合成-子流程]<br/>
     * 创建或删除表之前  检测表是否存在
     * IF NOT EXISTS
     *
     * @param exists exists
     * @return StringBuilder
     */
    @Override
    public StringBuilder checkTableExists(StringBuilder builder, boolean exists) {
        builder.append(" IF ");
        if (!exists) {
            builder.append("NOT ");
        }
        builder.append("EXISTS ");
        return builder;
    }

    @Override
    public StringBuilder tableName(StringBuilder builder, Table meta) {
        String tableName = meta.getName();
        String catalog = meta.getCatalog();
        if (StrUtil.isNotBlank(catalog)) {
            tableName = catalog + DELIMITER + tableName;
        }
        return builder.append(tableName);
    }

    @Override
    public StringBuilder body(StringBuilder builder, Table meta) {
        List<Column<?>> columns = meta.getColumns();
        if (CollUtil.isEmpty(columns)) {
            return builder;
        }
        builder.append(" (");
        columns(builder, meta);
        primary(builder, meta);
        builder.append(BR).append(")");
        return builder;
    }

    @Override
    public StringBuilder columns(StringBuilder builder, Table meta) {
        List<Column<?>> columns = meta.getColumns();
        builder.append(BR_TAB);
        // 属性定义
        for (Column<?> column : columns) {
            columnDefine(builder, column);
            builder.append(COMMA).append(BR_TAB);
        }
        return builder;
    }

    @Override
    public StringBuilder columnDefine(StringBuilder builder, Column<?> meta) {
        builder.append(meta.getName());
        // 子类去实现具体的类型
        type(builder, meta);
        nullable(builder, meta);
        defaultValue(builder, meta);
        increment(builder, meta);
        comment(builder, meta);
        return builder;
    }

    @Override
    public StringBuilder nullable(StringBuilder builder, Column<?> meta) {
        if (meta.isPrimaryKey()) {
            // 主键的必须为非空
            builder.append(" NOT NULL");
            return builder;
        }
        // 是否允许为空
        boolean nullable = meta.isNullable();
        if (nullable) {
            builder.append(" NULL");
            return builder;
        }
        builder.append(" NOT NULL");
        return builder;
    }

    @Override
    public StringBuilder defaultValue(StringBuilder builder, Column<?> meta) {
        //自增序列不要默认值
        boolean autoIncrement = meta.isAutoIncrement();
        if (autoIncrement) {
            return builder;
        }
        Object defaultValue = meta.getDefaultValue();
        if (Objects.isNull(defaultValue)) {
            return builder;
        }
        // 直接拼接默认值
        builder.append(" DEFAULT '").append(defaultValue).append("'");
        return builder;
    }


    @Override
    public StringBuilder primary(StringBuilder builder, Table meta) {
        List<Column<?>> columns = meta.getColumns();
        if (CollUtil.isEmpty(columns)) {
            return builder;
        }
        String primaryKeys = columns.stream().filter(Column::isPrimaryKey).map(Column::getName).collect(Collectors.joining(COMMA));
        builder.append("PRIMARY KEY (").append(primaryKeys).append(")");
        return builder;
    }

    @Override
    public StringBuilder indexes(StringBuilder builder, Index meta, String tableName) {
        builder.append("CREATE INDEX ")
                .append(meta.getName())
                .append(" ON ")
                .append(tableName)
                .append(" (")
                .append(String.join(COMMA, String.join(COMMA, meta.getColumnNames())))
                .append(" )")
                .append(";")
        ;
        return builder;
    }

    @Override
    public StringBuilder indexes(StringBuilder builder, Table meta) {
        List<Index> indexes = meta.getIndexes();
        if (CollUtil.isEmpty(indexes)) {
            return builder;
        }
        for (Index index : indexes) {
            builder.append(BR);
            indexes(builder, index, meta.getName());
            // 构建索引注释
            indexCommentOn(builder, index);
        }
        return builder;
    }

    @Override
    public StringBuilder tableCommentOn(StringBuilder builder, Table meta) {
        // 默认不做任何东西，由子类去重写
        return builder;
    }

    @Override
    public StringBuilder columnCommentOn(StringBuilder builder, Table meta) {
        // 默认不做任何东西，由子类去重写
        return builder;
    }

    @Override
    public StringBuilder indexCommentOn(StringBuilder builder, Index meta) {
        // 默认不做任何东西，由子类去重写
        return builder;
    }
}
